package com.jiangyg.mall.core.utils.tree;

import com.jiangyg.mall.core.utils.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 类描述：树形结构工具类
 *
 * @author jiangyg
 * @version 2.0
 * @date 2020-07-30
 */
public class TreeUtils {

    /**
     * 跟节点
     */
    private String root = "100000000000000000";

    /**
     * 原列表数据结构
     */
    private final List<Tree> sources;

    /**
     * 判断是否排除节点
     */
    private Predicate<Tree> excludePredicate;

    /**
     * 排序
     */
    private String comparator = TreeSort.class.getName();

    private TreeUtils(List<Tree> sources) {
        this.sources = sources;
    }

    private TreeUtils(List<Tree> sources, Predicate<Tree> excludePredicate) {
        this.sources = sources;
        this.excludePredicate = excludePredicate;
    }

    private TreeUtils(List<Tree> sources, String root) {
        this.sources = sources;
        this.root = root;
    }

    private TreeUtils(List<Tree> sources, Predicate<Tree> excludePredicate, String root) {
        this.sources = sources;
        this.excludePredicate = excludePredicate;
        this.root = root;
    }

    public static TreeUtils instance(List<Tree> sources) {
        return new TreeUtils(sources);
    }

    public static TreeUtils instance(List<Tree> sources, String root) {
        return new TreeUtils(sources, root);
    }

    public static TreeUtils instance(List<Tree> sources, Predicate<Tree> excludePredicate) {
        return new TreeUtils(sources, excludePredicate);
    }

    public static TreeUtils instance(List<Tree> sources, Predicate<Tree> excludePredicate, String root) {
        return new TreeUtils(sources, excludePredicate, root);
    }

    public void setComparator(String comparator) {
        this.comparator = comparator;
    }

    /**
     * 功能描述：获取属性结构
     *
     * @return 树形结构
     */
    public List<Tree> getTree() throws Exception {
        // 树形结构处理
        Map<String, List<Tree>> collect = sources.stream().collect(Collectors.groupingBy(Tree::getPid));
        collect.values().stream().flatMap(Collection::stream).forEach(n -> n.setChildren(collect.get(n.getId())));
        List<Tree> rootList = collect.get(this.root);
        // 剔除无用目录
        if (excludePredicate != null && CollectionUtils.isNotEmpty(rootList)) {
            deleteUselessMenu(rootList);
        }
        // 节点排序处理
        if (StringUtils.isNotBlank(comparator) && CollectionUtils.isNotEmpty(rootList)) {
            final Comparator<Tree> comparat = (Comparator<Tree>) Class.forName(comparator).newInstance();
            treeSort(rootList, comparat);
        }
        return rootList;
    }

    /**
     * 功能描述：删除无用目录
     *
     * @param dataList 要处理数据集
     */
    private void deleteUselessMenu(final List<Tree> dataList) {
        Assert.notEmpty(dataList);
        final Iterator<Tree> iterator = dataList.iterator();
        while (iterator.hasNext()) {
            final Tree data = iterator.next();
            final List<Tree> children = data.getChildren();
            if (CollectionUtils.isNotEmpty(children)) {
                deleteUselessMenu(children);
            }
            if (excludePredicate != null && excludePredicate.test(data)) {
                iterator.remove();
            }
        }
    }

    /**
     * 功能描述：数排序
     *
     * @param dataList   要排序的数据集
     * @param comparator 排序规则
     */
    private void treeSort(final List<Tree> dataList, final Comparator<Tree> comparator) {
        Assert.notEmpty(dataList);
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataList.sort(comparator);
        }
        for (Tree data : dataList) {
            final List<Tree> children = data.getChildren();
            if (CollectionUtils.isNotEmpty(children)) {
                treeSort(children, comparator);
            }
        }
    }

}
